package org.demo.treeeditor;

import java.util.ArrayList;
import java.util.List;

import org.boxlayout.gui.BoxLayoutEngine;
import org.boxlayout.gui.VisualElement;
import org.boxlayout.gui.layout.LayoutEnum;
import org.boxlayout.gui.type.ColorEnum;
import org.boxlayout.gui.utils.VisualElementXmlLoader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Node {

    BoxLayoutEngine ble;
    VisualElement visual;
    VisualElement bodyContainer;
    VisualElement nameContainer;
    VisualElement childLayout;
    VisualElement childContainer;
    VisualElement expandCollapseIcon;

    String name;
    ColorEnum defaultColor = ColorEnum.GRAY;
    ColorEnum color = null;	

    Node parent;
    protected List<Node> childs = new ArrayList<Node>();
    protected Boolean root = false;
    protected Boolean expanded = false;

    protected Float padding = 0.00f;
    //boolean expended = true;
    static String nodeElementName = "node";
    static String valueAttributeName = "value";


    public Node(BoxLayoutEngine ble) {
	this.ble = ble;
	initVisual();
    }

    /*public Node(VisualElement visualElement){
	ble = visualElement.getBoxLayoutEngine();
	visual = visualElement;
	nameContainer = visualElement.findFirstByName("name");
	bodyContainer = visualElement.findFirstByName("body");
	expandCollapseIcon = visualElement.findFirstByName("expandCollapseIcon");
    }*/

    public Node initVisual() {
	visual = ble.getVisualElementXmlLoader().get("demo/data/treeEditor/node.bl.xml","visual").clone();
	nameContainer = visual.findFirstByName("name");
	bodyContainer = visual.findFirstByName("body");
	expandCollapseIcon = visual.findFirstByName("expandCollapseIcon");
	/*color = defaultColor;

		bodyContainer = ble.createElement().setLayout(LayoutFactory.getInstance().getHorizontalLayout()).setAlpha(0f);

		expendCollapseIcon = ble.createElement().setRounded(true).setAlpha(1f).setColor(ColorEnum.WHITE).setPadding(0.04f).setLayout(LayoutFactory.getInstance().getHorizontalLayout())
		.add(
			ble.createElement().setRounded(true).setAlpha(1f).setColor(ColorEnum.BLACK).setPadding(0.05f).setTextColor(ColorEnum.LIGHTGRAY).setText("+")
		);

		nameContainer = ble.createElement()
		//.setColor(color).setColor2(ColorEnum.LIGHTGRAY)
		//.setColor(ColorEnum.BLACK).setColor2(ColorEnum.BLACK).setTextColor(ColorEnum.WHITE)
		//.setColor(ColorEnum.WHITE).setColor2(ColorEnum.WHITE).setTextColor(ColorEnum.BLACK)
		.setColor(ColorEnum.BLACK).setColor2(ColorEnum.BLACK).setTextColor(ColorEnum.LIGHTGRAY)
		.setPadding(0.15f).setText(name).setTextScale(0.005f).setRounded(true).setAlpha(1.0f)
		.setId(1);

		visual = ble.createElement().setLayout(LayoutFactory.getInstance().getVerticalLayout()).setId(0)
		.setPadding(0.00f).setColor(ColorEnum.WHITE).setAlpha(0.0f);

		VisualElement border = ble.createElement().setColor(ColorEnum.WHITE)
		.setRounded(true).setAlpha(1.0f).setPadding(0.04f).setLayout(LayoutFactory.getInstance().getVerticalLayout())
		;
		border.add(nameContainer);
		bodyContainer.add(border);
		bodyContainer.add(expendCollapseIcon.setEnable(false));
		visual.add(bodyContainer);*/

	return this;
    }

    public VisualElement getVisual(){
	return visual;
    }


    public void setText(String string) {
	nameContainer.setText(string);
    }

    public String getText() {
	return nameContainer.getText();
    }

    public VisualElement getNameContainerVisualElement(){
	return nameContainer;
    }

    void createChildLayoutAndContainer(){
	VisualElement newChildLayout = ble.getVisualElementXmlLoader().get("demo/data/treeEditor/node.bl.xml","childLayout").clone();
	childContainer = newChildLayout.findFirstByName("childContainer");
	
	/*childContainer = ble.createElement().setLayout(LayoutFactory.getInstance().getVerticalLayout())
	.setPadding(padding).setColor(ColorEnum.WHITE).setId(4).setAlpha(0.0f);

	VisualElement newChildLayout = ble.createElement().setLayout(LayoutFactory.getInstance().getHorizontalLayout())
	.setPadding(padding).setAlpha(0.0f).setId(2)
	.add(ble.createElement().setPadding(padding).setPreferedWidth(0.2f)
		.setPreferedHeight(0.1f).setAlpha(0.0f).setId(3)
	)
	.add(childContainer);
	*/
	if (childLayout == null) {
	    visual.add(newChildLayout);
	} else {
	    visual.replace(childLayout, newChildLayout);
	}
	childLayout = newChildLayout;
    }



    public void appendChild(Node node){
	insertBefore(null,node);
    }

    public void insertBefore(Node futurePreviousNode,Node newNode){
	if(childContainer==null){
	    createChildLayoutAndContainer();
	}
	if(futurePreviousNode==null){
	    childContainer.add(newNode.getVisual());
	    childs.add(newNode);
	}else{
	    childContainer.insertBefore(futurePreviousNode.getVisual(),newNode.getVisual());
	    childs.add(childs.indexOf(futurePreviousNode),newNode);
	}
	if(!childs.isEmpty()){
	    setExpanded(true);
	}
	newNode.setParent(this);
	updateExpendCollapseButton();
    }




    public VisualElement getChildContainer() {
	return childContainer;
    }

    public Node setParent(Node parent){
	this.parent=parent;
	return this;
    }

    public Node getParent(){
	return parent;
    }

    public List<Node> getChilds(){
	return childs;
    }

    public Node getChild(Integer i) {
	Node result = null;
	try{
	    result = (Node)getChilds().get(i);
	}catch(IndexOutOfBoundsException e){}
	return result;
    }

    public Node setRoot(Boolean bool) {
	root=bool;
	return this; 
    }

    public Node getPreviousBrother(){
	Node result = null;
	if (!root)  {
	    Integer index = parent.getChilds().indexOf(this);
	    if (0 < index) {
		result =  parent.getChilds().get(index - 1);
		/*if(result==null){
		    result = getParent();
		}*/
	    }
	}
	return result;
    }

    public Node getNextBrother() {
	Node result= null;
	if (!root) {
	    Integer index = parent.getChilds().indexOf(this);
	    //am i the last brother
	    if (index < parent.getChilds().size() - 1) {
		result =  parent.getChilds().get(index + 1);
		/* cant happens if(result==null){
				result = parent.getNext();
			}*/
	    }
	}
	return result;
    }


    public Node getNextSibling() {
	Node result;
	if(hasChilds()&&expanded){
	    result = getChild(0);
	}else{
	    result = getNextBrother();
	    if(result==null&&!root){
		Node currentParent = getParent();
		result = currentParent.getNextBrother();
		while(result==null&&!currentParent.root){
		    currentParent = currentParent.getParent();
		    result = currentParent.getNextBrother();
		}
	    }
	}
	return result;
    }


    public Node getPreviousSibling() {
	Node result;

	result = getPreviousBrother();
	if(result==null){
	    if(!root){
		result = getParent();
	    }	    
	}else{
	    Node deeper = getLastNext(result);
	    if (deeper!=null){
		result = deeper;
	    }
	}

	return result;
    }

    public Node getLastNext(Node node) {
	Node result = null;
	if(node.hasChilds()&&node.expanded){
	    result = node.getLastChildren();
	    Node deeper = getLastNext(node.getLastChildren());
	    if(deeper!=null){
		result = deeper;
	    }
	}
	return result;
    }



    Node getLastChildren() {
	Node result = null;
	if(hasChilds()){
	    result = getChild(childs.size()-1);
	}
	return result;
    }

    public Boolean hasChilds() {
	return getChilds().size()>0;
    }

    public void setExpanded(Boolean expend) {
	if (!expanded && expend) {
	    childLayout.setEnable(true);
	    ble.reLayout();
	} else if (expanded && !expend) {
	    childLayout.setEnable(false);
	    ble.reLayout();
	}
	expanded = expend;
    }

    public void remove(Node current) {
	childs.remove(current);
	childContainer.remove(current.getVisual());
	if(childs.isEmpty()){
	    setExpanded(false);
	}
	updateExpendCollapseButton();
    }


    public void expendCollapse(){
	if(expanded){
	    collapse();
	}else{
	    expand();
	}

    }
    public void expand(){
	if(!expanded&&childContainer!=null){
	    childContainer.setEnable(true);
	    expanded = true;
	    updateExpendCollapseButton();
	}
    }

    public void collapse(){
	if(expanded&&childContainer!=null){
	    childContainer.setEnable(false);
	    expanded = false;
	    updateExpendCollapseButton();
	}
    }

    public void clear(){
	childs.clear();
	if(childContainer!=null){
	    childContainer.clear();
	}
	setExpanded(false);
    }

    void updateExpendCollapseButton(){
	expandCollapseIcon.setEnable(hasChilds()&&!expanded);
    }

    public org.w3c.dom.Node toXml(Document doc){
	Element elem = doc.createElement(nodeElementName);
	elem.setAttribute(valueAttributeName, nameContainer.getText());
	for(Node current:childs){
	    elem.appendChild(current.toXml(doc));
	}
	return (org.w3c.dom.Node)elem;
    }

    public Node fromXml(org.w3c.dom.Node node){

	org.w3c.dom.Node attributeNode = node.getAttributes().getNamedItem(valueAttributeName);
	if(attributeNode!=null){
	    nameContainer.setText(attributeNode.getNodeValue());
	}
	for(Integer i = 0,n = node.getChildNodes().getLength();i<n;i++){
	    org.w3c.dom.Node current = node.getChildNodes().item(i);
	    Node newNode = new Node(ble);
	    newNode.fromXml(current);
	    appendChild(newNode);
	}

	return this;
    }

}
